///////////////////////////////////////////////////////////////////////////////////////
//
//	DoD Smoke Grenades 2
//		- Version 1.3
//		- 11.05.2007
//		- original: Zor
//		- modified: diamond-optic
//
//////////////////////////////////////////////////////////////////////////////////
//
// Credits:
//
//	- Zor: original DoD Smoke Grenades plugin (v0.7a)
//	- Original Thread: http://www.dodplugins.net/forums/showthread.php?t=9
//
// Information:
//
//	- Allows you to throw smoke grenades... obviously...
//
//	- Seperate loadouts for each class
//	- Voice command to yell out "Smoke Em!"
//	- Take damage when another player hits you with their smoke grenade
//	- Choking sound & damage within a certain radius of a grenade
//	- Flood protection on the voice command to prevent spam
//
//	- Psychostats compatible log messages
//
//	- File consistency on the smoke sprite, no more cheaters replacing it..
//
//	* works on linux & win32 servers *
//
//////////////////////////////////////////////////////////////////////////////////
//
// File Placement:
//
//	smoke_grenade.spr	-->	../dod/sprites/
//	explode_smoke.wav	-->	../dod/sound/misc/
//	cough1.wav		-->	../dod/sound/player/
//	cough2.wav		-->	../dod/sound/player/
//	brit_smoke.wav		-->	../dod/sound/player/
//	ger_smoke.wav		-->	../dod/sound/player/
//	us_smoke.wav		-->	../dod/sound/player/
//
//////////////////////////////////////////////////////////////////////////////////
//
// Commands:
//
//	throw_smoke		//throws a smoke grenade
//	voice_smoke		//yells out "Smoke Em!"
//
//////////////////////////////////////////////////////////////////////////////////
//
// CVARs:
//
//	dod_smokegrenades "1"			//Turn on(1)/off(0)
//
//	dod_smoke_warncrc "2"			//CRC warning setting (on inconsistent smoke sprite)
//						//	0 = say nothing
//						//	1 = tell admins
//						//	2 = tell public
//
//	dod_smoke_spread "80"			//Spread (from the grenade itself)
//
//	dod_smoke_size_min "15"			//Minimum smoke sprite size
//	dod_smoke_size_max "70"			//Maximum smoke sprite size
//
//	dod_smoke_sprites "4"			//Number of smoke sprites created each second
//
//	dod_smoke_duration "15"			//How many seconds grenades will give off smoke
//
//	dod_smoke_startdelay "2.0"		//How many seconds after throw till grenade gives off smoke
//	dod_smoke_throwdelay "1.0"		//How many seconds to delay between each throw
//
//	dod_smoke_choke "1"			//Turn on(1)/off(0) choking sound
//	dod_smoke_choke_radius "65"		//Radius from smoke grenade for choking
//	dod_smoke_choke_chance "2"		//1 in # chance of playing choking sound
//	dod_smoke_choke_dmg "1"			//Turn on(1)/off(0) choke damage
//	dod_smoke_choke_dmg_amount "5"		//Amount of damage given
//	dod_smoke_choke_dmg_chance "5"		//1 in # chance of giving damage
//
//	dod_smoke_hitdmg "1"			//Turn on(1)/off(0) hit damage (when grenade hits a player)
//	dod_smoke_hitdmg_amount "20"		//Amount of damage given per hit
//
//	dod_smoke_floodtime "2.0"		//How many seconds between using 'voice_smokeup' command
//
//	//Messages - Turn on(1)/off(0)
//	dod_smoke_msg_join "0"			//Shows commands 30 seconds after player has joined the server
//	dod_smoke_msg_spawn "0"			//Shows how many smoke grenades you have when you spawn
//	dod_smoke_msg_throw "1"			//Shows how many smoke grenades you have left after throwing one
//
//	//Number of grenades each class spawns with:
//	dod_smoke_garand "2"
//	dod_smoke_carbine "2"
//	dod_smoke_thompson "1"
//	dod_smoke_grease "1"
//	dod_smoke_sniper "2"
//	dod_smoke_bar "1"
//	dod_smoke_30cal "2"
//	dod_smoke_bazooka "3"
//	dod_smoke_kar "2"
//	dod_smoke_k43 "2"
//	dod_smoke_mp40 "1"
//	dod_smoke_mp44 "1"
//	dod_smoke_scharfschutze "2"
//	dod_smoke_fg42 "1"
//	dod_smoke_scoped_fg42 "1"
//	dod_smoke_mg34 "2"
//	dod_smoke_mg42 "2"
//	dod_smoke_panzerjager "3"
//	dod_smoke_enfield "2"
//	dod_smoke_sten "1"
//	dod_smoke_marksman "2"
//	dod_smoke_bren "1"
//	dod_smoke_piat "3"
//
//////////////////////////////////////////////////////////////////////////////////
//
// Extra:
//
//	- The MAX_SMOKE define sets the max number of smoke grenades allowed at once 
//		* Be careful messing with this one (default setting: 32)
//		* Setting this too high could make your server vulnerable to crashing
//
//	- The FULL_PRECACHE define controls whether all files are precached or not 
//		* If you find that some sounds dont work, enable this
//		* If you get 'file not precached' errors, enable this
//
//////////////////////////////////////////////////////////////////////////////////
//
// Change Log:
//
//	- 04.25.07 - Version 1.0
//		Finally Released
//
//	- 06.24.07 - Version 1.1
//		Fixed a cvar mistake (this also fixes incorrect hit damage)
//		changed returns to FMRES on fakemeta forwards
//		Added CVAR to control delay between throws
//		Added MAX_SMOKE define to limit max smoke nades at once
//		Hopefully fixed the consistency function from hooking all bad files
//		Removed default DoD sounds from precache (dod already precaches them)
//		Added FULL_PRECACHE define to enable precaching all files
//		Improved weaponstats log msgs and added victim's death
//		Fixed bug with setting user kills
//		Various changes & improvements throughout the code
//
//	- 07.30.07 - Version 1.2
//		Fixed rare runtime error in damage/choke functions
//		Adjusted default choke/damage radii
//		Slight changes to consistency messages
//
//	- 11.05.07 - Version 1.3
//		Fix for annoying sound loop on stuck grenade
//
///////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////
// Module Include
//
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <dodx>
#include <dodfun>

///////////////////////////////////////////////////////////////////////////////////////
// Version Control
//
new AUTH[] = "AMXX DoD Team"
new PLUGIN_NAME[] = "DoD Smoke Grenades 2"
new VERSION[] = "1.3"

/////////////////////////////////////////////////
// Max Smoke Grenades Allowed At Same Time
//
#define MAX_SMOKE 32

/////////////////////////////////////////////////
// FULL PRECACHE   (1=ON/0=OFF)
//
// Enable this if you find that some of
// the sounds dont play or they return
// precache errors.
// 
#define FULL_PRECACHE 0

/////////////////////////////////////////////////
// Debug Mode (1=ON/0=OFF)
//
// this enables the "debug_givesmoke" command
// which will give you +5 smoke grenades...
// really useful for me when making changes,
// and i guess it could also be useful for
// trying new cvar settings out...
//
#define DEBUG_MODE	1

/////////////////////////////////////////////////
// Globals
//
new smoke
new playerGrensCount[33]
new bool:log_block_state = false
new bool:g_round_restart = false
new bool:g_startGrenade[1024] = { false, ... }
new Float:g_finishTime[1024] = { 0.0, ... }
new Float:g_nextThrow[33] = { 0.0, ... }
new Float:g_NextSay[33] = { 0.0, ... }
new Float:hitTime[33]
new gMsgDeathMsg, gMsgFrags
new gibs_shrapnel
new smokeCount = 0

/////////////////////////////////////////////////
// Files
//
new fileNames[16][] =
{
	"sprites/smoke_grenade.spr",
	"models/mapmodels/smoke_grenade.mdl",
	"weapons/grenthrow.wav",
	"weapons/grenpinpull.wav",
	"weapons/grenade_hit1.wav",
	"weapons/grenade_hit2.wav",
	"weapons/grenade_hit3.wav",
	"common/bodysplat.wav",
	"player/sprintgrunts.wav",
	"player/cough1.wav",
	"player/cough2.wav",
	"player/brit_smoke.wav",
	"player/us_smoke.wav",
	"player/ger_smoke.wav",
	"misc/explode_smoke.wav",
	"models/shrapnel.mdl"
}

enum
{
	sprites,
	model,
	throw,
	pin,
	hit1,
	hit2,
	hit3,
	splat,
	grunt,
	cough1,
	cough2,
	brit_smokeup,
	us_smokeup,
	ger_smokeup,
	explode_smoke,
	shrapnel
}
//
///////////////////////////////////////////////////////////////////////////////////////
//
// CVAR Pointers
//
new p_smoke, p_smoke_warncrc, p_smoke_sprites, p_smoke_duration
new p_spread, p_size_min, p_size_max
new p_choke, p_choke_radius, p_choke_chance, p_damage, p_damage_amount, p_damage_chance
new p_hitdmg, p_hitdmg_amount
new p_startdelay, p_throwdelay, p_floodtime
new p_msg_throw, p_msg_spawn, p_msg_join

///////////////////////////////////////////////////////////////////////////////////////
//
// Initialization
//
public plugin_init()
{
	// Register this plugin
	register_plugin(PLUGIN_NAME, VERSION, AUTH)
	
	//public tracking cvar
	register_cvar("dod_smokegrenade2_stats", VERSION, FCVAR_SERVER|FCVAR_SPONLY)

#if DEBUG_MODE == 1

	//debug command (gives you +5 more smokes)
	register_concmd("debug_givesmoke","debug_givesmoke",ADMIN_IMMUNITY,"Add 5 smoke grenades to your total count")

#endif
	
	// Register Client Commands for this Plugin
	register_clcmd("throw_smoke", "throwsmoke", 0, "- Will throw a smoke grenade") 
	register_clcmd("voice_smoke", "say_smoke", 0, "- Will yell out ^"Smoke Em!^"") 
		
	// Register Event Hooks	
	register_event("RoundState", "round_message", "a", "1=1", "1=3", "1=4", "1=5")
	
	//Get Message IDs
	gMsgDeathMsg = get_user_msgid("DeathMsg")
	gMsgFrags = get_user_msgid("Frags")

	//Register Forwards
	register_forward(FM_Think, "draw_smoke")
	register_forward(FM_Touch, "grenade_touch")
	register_forward(FM_AlertMessage,"block_log")
	
	//client spawn
	register_event("ResetHUD", "player_spawn", "be")	
	register_clcmd("fullupdate", "clcmd_fullupdate")	//blocks fullupdate cmd
	
	// Register CVARS
	p_smoke = register_cvar("dod_smokegrenades", "1")
	
	p_smoke_warncrc = register_cvar("dod_smoke_warncrc", "2")
	p_floodtime = register_cvar("dod_smoke_floodtime", "2.0")
	
	p_spread = register_cvar("dod_smoke_spread", "80")
	p_size_min = register_cvar("dod_smoke_size_min", "15")
	p_size_max = register_cvar("dod_smoke_size_max", "70")
	
	p_smoke_sprites = register_cvar("dod_smoke_sprites", "4")
	p_smoke_duration = register_cvar("dod_smoke_duration", "15")
	p_startdelay = register_cvar("dod_smoke_startdelay", "2.0")
	p_throwdelay = register_cvar("dod_smoke_throwdelay", "1.0")
	
	p_choke = register_cvar("dod_smoke_choke", "1")	
	p_choke_radius = register_cvar("dod_smoke_choke_radius", "65")
	p_choke_chance = register_cvar("dod_smoke_choke_chance", "2")
	p_damage = register_cvar("dod_smoke_choke_dmg", "1")
	p_damage_amount = register_cvar("dod_smoke_choke_dmg_amount", "5")
	p_damage_chance = register_cvar("dod_smoke_choke_dmg_chance", "3")
	
	p_hitdmg = register_cvar("dod_smoke_hitdmg", "1")
	p_hitdmg_amount = register_cvar("dod_smoke_hitdmg_amount", "20")
	
	p_msg_join = register_cvar("dod_smoke_msg_join", "0")
	p_msg_spawn = register_cvar("dod_smoke_msg_spawn", "0")
	p_msg_throw = register_cvar("dod_smoke_msg_throw", "1")
	
	// Max grenades per class
	register_cvar("dod_smoke_garand", "2")
	register_cvar("dod_smoke_carbine", "2")
	register_cvar("dod_smoke_thompson", "1")
	register_cvar("dod_smoke_grease", "1")
	register_cvar("dod_smoke_sniper", "2")
	register_cvar("dod_smoke_bar", "1") 
	register_cvar("dod_smoke_30cal", "2")
	register_cvar("dod_smoke_bazooka", "3")
	register_cvar("dod_smoke_kar", "2")
	register_cvar("dod_smoke_k43", "2")
	register_cvar("dod_smoke_mp40", "1")
	register_cvar("dod_smoke_mp44", "1")
	register_cvar("dod_smoke_scharfschutze", "2")
	register_cvar("dod_smoke_fg42", "1")
	register_cvar("dod_smoke_scoped_fg42", "1")
	register_cvar("dod_smoke_mg34", "2")
	register_cvar("dod_smoke_mg42", "2")
	register_cvar("dod_smoke_panzerjager", "3")
	register_cvar("dod_smoke_enfield", "2")
	register_cvar("dod_smoke_sten", "1")
	register_cvar("dod_smoke_marksman", "2")
	register_cvar("dod_smoke_bren", "1")
	register_cvar("dod_smoke_piat", "3")
}

///////////////////////////////////////////////////////////////////////////////////////
//
// Pre-Cache the models/sprites/sounds
//
public plugin_precache() 
{
	smoke = precache_model(fileNames[sprites])		// smoke sprite
	enforce(fileNames[sprites])
	
	gibs_shrapnel = precache_model(fileNames[shrapnel])
	
	precache_model(fileNames[model])			// grenade model
	precache_sound(fileNames[pin])				// grenade pin pulling sound
	precache_sound(fileNames[cough1])			// cough
	precache_sound(fileNames[cough2])			// cough
	precache_sound(fileNames[brit_smokeup])			// voice
	precache_sound(fileNames[us_smokeup])			// voice
	precache_sound(fileNames[ger_smokeup])			// voice
	precache_sound(fileNames[explode_smoke])		// smoke explode
	
#if FULL_PRECACHE == 1

	//DoD already precaches???
	precache_sound(fileNames[throw])			// grenade throwing sound
	precache_sound(fileNames[hit1])				// grenade hit sound
	precache_sound(fileNames[hit2])				// grenade hit sound
	precache_sound(fileNames[hit3])				// grenade hit sound
	precache_sound(fileNames[splat])			// splat
	precache_sound(fileNames[grunt])			// grunt
	
#endif
	
}

///////////////////////////////////////////////////////////////////////////////////////
//
// Block fullupdate
//
public clcmd_fullupdate() 
{
	return PLUGIN_HANDLED	
}

///////////////////////////////////////////////////////////////////////////////////////
//
// Join Message
//
public client_putinserver(id)
{
	if(!is_user_bot(id) && is_user_connected(id) && get_pcvar_num(p_smoke) && get_pcvar_num(p_msg_join)) 
		set_task(30.0, "ShowMsg", id)
}

public ShowMsg(id)
{
	if(!is_user_bot(id) && is_user_connected(id)) 
		client_print(id, print_chat, "DoD Smoke Grenades ENABLED! Commands: throw_smoke & voice_smoke")
}

///////////////////////////////////////////////////////////////////////////////////////
//
// Throw the actual grenade
//
public throwsmoke(id) 
{
	new Float:gametime = get_gametime()
	
	if(!get_pcvar_num(p_smoke) || !is_user_alive(id) || !playerGrensCount[id] || g_round_restart || gametime < g_nextThrow[id] || smokeCount >= MAX_SMOKE)
		return PLUGIN_HANDLED
				
	new Float:TumbleVector[3] 	//= {-250.0, -420.0, -100.0}
					
	TumbleVector[0] = random_float(350.0,-350.0)
	TumbleVector[1] = random_float(500.0,-500.0)
	TumbleVector[2] = random_float(200.0,-200.0)

	// create the grenade
	new grenid = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
	
	if(!grenid || !pev_valid(grenid))
		return PLUGIN_HANDLED
		
	// calculate how hard to throw the grenade based on the aim angle
	new Float:vAngle[3]
	new Float:punchAngle[3]
	new Float:throwAngle[3]

	pev(id, pev_v_angle, vAngle)
	pev(id, pev_punchangle, punchAngle)
	throwAngle[0] = vAngle[0] + punchAngle[0] * 7

	if(throwAngle[0] < 0) 
		throwAngle[0] = -10 + throwAngle[0] * ((90 - 10) / 90.0)

	else
		throwAngle[0] = -10 + throwAngle[0] * ((90 + 10) / 90.0)

	new Float:flVel = (90 - throwAngle[0]) * 5

	// limit out velocity to a maximum of 1200
	if(flVel > 1200.0)	
		flVel = 1200.0

	// show throw anim  ** doesnt work **
	//set_pev(id, pev_sequence, 82)
	
	new Float:PlayerOrigin[3]
	new Float:velocity[3]

	// throw angle and velocity
	velocity_by_aim(id, floatround(flVel), velocity)
	
	// Make the throw sound
	emit_sound(id, CHAN_WEAPON, fileNames[throw], 0.9, ATTN_NORM, 0, PITCH_NORM)

	// get the player origin
	pev(id, pev_origin, PlayerOrigin)
	PlayerOrigin[2] += 32
	
	new Float:angles[3]
	pev(id, pev_v_angle, angles)
	new Float:forward_angles[3]
	angle_vector(angles, ANGLEVECTOR_FORWARD, forward_angles)

	PlayerOrigin[0] += (forward_angles[0] * 10)
	PlayerOrigin[1] += (forward_angles[1] * 10)
	PlayerOrigin[2] += (forward_angles[2] * 10)
	
	set_pev(grenid, pev_classname, "dod_smoke")	
	set_pev(grenid, pev_origin, PlayerOrigin)
	engfunc(EngFunc_SetModel, grenid, fileNames[model])
	set_pev(grenid, pev_movetype, MOVETYPE_BOUNCE)	
	set_pev(grenid, pev_solid, SOLID_BBOX)	
	set_pev(grenid, pev_friction, 0.7)	
	set_pev(grenid, pev_gravity, 0.5)	
	set_pev(grenid, pev_velocity, velocity)	
	set_pev(grenid, pev_avelocity, TumbleVector)	
	set_pev(grenid, pev_owner, id)	
	
	new Float:duration = get_pcvar_float(p_smoke_duration)
	new Float:start_delay = get_pcvar_float(p_startdelay)
	
	set_pev(grenid, pev_nextthink, gametime + start_delay)
	
	g_finishTime[grenid] = (gametime + start_delay + duration)

	g_startGrenade[grenid] = true
	emit_sound(grenid, CHAN_WEAPON, fileNames[pin], 1.0, ATTN_NORM, 0, PITCH_NORM)
	
	//set the nade's bbox size... still needs more work...
	//new Float:mina[3], Float:maxa[3]			
	//mina[0]=-2.0
	//mina[1]=-3.0
	//mina[2]=0.0
	//maxa[0]=2.0
	//maxa[1]=3.0
	//maxa[2]=2.0
	//set_pev(grenid, pev_size, mina, maxa)
	
	playerGrensCount[id]--
	smokeCount++
	
	g_nextThrow[id] = (gametime + get_pcvar_float(p_throwdelay))
	
	if(get_pcvar_num(p_msg_throw))
		client_print(id, print_chat, "You have %d Smoke %s left...", playerGrensCount[id], (playerGrensCount[id] != 1) ? "Grenades" : "Grenade")
	
	new steam[32],teamname[32],name[32]
	get_user_authid(id, steam, 31)
	dod_get_pl_teamname(id, teamname, 31)
	get_user_name(id, name, 31)
											
	log_message("^"%s<%d><%s><%s>^" triggered ^"weaponstats^" (weapon ^"smoke_grenade^") (shots ^"1^") (hits ^"0^") (kills ^"0^") (headshots ^"0^") (tks ^"0^") (damage ^"0^") (deaths ^"0^") (score ^"0^")",name,get_user_userid(id),steam,teamname)		
	
	return PLUGIN_HANDLED
}

///////////////////////////////////////////////////////////////////////////////////////
//
// Allows players to Yell Out SMOKE UP!
//
public say_smoke(id)
{
	if(!get_pcvar_num(p_smoke) || !is_user_alive(id))
		return PLUGIN_HANDLED
				
	new Float:current_time = get_gametime()
	new Float:flood_time = get_pcvar_float(p_floodtime)
		
	// check for exessive spamming
	if(g_NextSay[id] > current_time)
		{
		g_NextSay[id] = current_time + (flood_time * 2)
		
		//client_print(id, print_chat, "Chill out, you're flooding the server!")
		
		return PLUGIN_HANDLED
		}
	
	g_NextSay[id] = current_time + flood_time
	
	new sound_to_play = 0
	new is_brit = dod_get_map_info(MI_ALLIES_TEAM)
	new team = get_user_team(id)

	// Check if its Allies, If so is it a brit map?
	if(team == 1 && is_brit == 1)
		sound_to_play = brit_smokeup
		
	else if(team == 1)
		sound_to_play = us_smokeup
		
	else
		sound_to_play = ger_smokeup
	
	
	emit_sound(id, CHAN_VOICE, fileNames[sound_to_play], 0.8, ATTN_NORM, 0, PITCH_NORM)
		
	client_cmd(id,"say_team Smoke Em!")
		
	return PLUGIN_HANDLED 
}

///////////////////////////////////////////////////////////////////////////////////////
//
// Make the grenade generate smoke
//
public draw_smoke(grenid) 
{	
	if(!pev_valid(grenid))
		return FMRES_IGNORED
	
	new classname[32]
	pev(grenid,pev_classname, classname, 31)
	
	if(equali(classname,"dod_smoke") && !g_round_restart)
		{			
		if(get_gametime() < g_finishTime[grenid])
			{
			// Emit the sound
			if(g_startGrenade[grenid])
				{
				emit_sound(grenid, CHAN_WEAPON, fileNames[explode_smoke], 0.8, ATTN_NORM, 0, PITCH_NORM)
				g_startGrenade[grenid] = false
						
				new Float:origin[3], iOrigin[3]
				pev(grenid, pev_origin, origin)
				
				iOrigin[0] = floatround(origin[0])
				iOrigin[1] = floatround(origin[1])
				iOrigin[2] = floatround(origin[2])+2
						
				message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
				write_byte(TE_SPARKS)
				write_coord(iOrigin[0])
				write_coord(iOrigin[1])
				write_coord(iOrigin[2])
				message_end()
				
				message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
				write_byte(TE_DLIGHT)
				write_coord(iOrigin[0])
				write_coord(iOrigin[1])
				write_coord(iOrigin[2])
				write_byte(15)
				write_byte(192)
				write_byte(192)
				write_byte(192)
				write_byte(3)
				write_byte(25)
				message_end()
				
				message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
				write_byte(TE_BREAKMODEL)
				write_coord(iOrigin[0]) // x
				write_coord(iOrigin[1]) // y
				write_coord(iOrigin[2]+3) // z
				write_coord(5) // size x
				write_coord(5) // size y
				write_coord(5) // size z
				write_coord(random_num(-40,40)) // velocity x
				write_coord(random_num(-40,40)) // velocity y
				write_coord(random_num(10,100)) // velocity z
				write_byte(10) // random velocity
				write_short(gibs_shrapnel) // model
				write_byte(random_num(4,8)) // count
				write_byte(25) // life
				write_byte(0x02) // flags (0x02=metal / 0x10=smoke)
				message_end()
				}
			else
				{
				//bring in some smoke..
				new count = get_pcvar_num(p_smoke_sprites)
				make_smoke(grenid,count)
	
				// Do the damage & choke
				funcDamageChoke(grenid)
				}
	
			// Set the next think
			set_pev(grenid, pev_nextthink, get_gametime() + 1.0)
			}
		else
			{
			// trigger removal and re-use of the grenade as per the delay setting
			engfunc(EngFunc_RemoveEntity, grenid)
			
			smokeCount--
			g_startGrenade[grenid] = false
			}
		}
	
	return FMRES_IGNORED
}

///////////////////////////////////////////////////////////////////////////////////////
//
// Make Smoke
//
make_smoke(grenid,count)
{
	new Float:GrenOrigin[3], iOrigin[3]
	pev(grenid, pev_origin, GrenOrigin)
	
	iOrigin[0] = floatround(GrenOrigin[0])
	iOrigin[1] = floatround(GrenOrigin[1])
	iOrigin[2] = floatround(GrenOrigin[2])
	
	new pos_spread = get_pcvar_num(p_spread)
	new neg_spread = -(pos_spread)
	new min_size = get_pcvar_num(p_size_min)
	new max_size = get_pcvar_num(p_size_max)
	
	for(new i=0; i < count; i++)
		{	
		// Start the message
		message_begin(MSG_BROADCAST, SVC_TEMPENTITY, iOrigin)
		write_byte(TE_SMOKE)
		write_coord(iOrigin[0] + random_num(neg_spread,pos_spread))
		write_coord(iOrigin[1] + random_num(neg_spread,pos_spread))
		write_coord(iOrigin[2] - 26)	//30
		write_short(smoke)
		write_byte(random_num(min_size,max_size))
		write_byte(random_num(1,4))
		message_end()
		// End the message
		}
}

///////////////////////////////////////////////////////////////////////////////////////
//
// Check for Damage/Choking
//
public funcDamageChoke(grenid)
{
	new choke = get_pcvar_num(p_choke)
	new damage = get_pcvar_num(p_damage)
	
	if(!choke && !damage)
		return PLUGIN_HANDLED
	
	new Float:GrenOrigin[3], ent = -1
	pev(grenid, pev_origin, GrenOrigin)
		
	new Float:radius = get_pcvar_float(p_choke_radius)
	
	while((ent = engfunc(EngFunc_FindEntityInSphere,ent,GrenOrigin,radius)) != 0)
		{
		new classname[32]
		pev(ent,pev_classname,classname,31)
		
		if(equali(classname,"player") && is_user_alive(ent))
			{
			if(choke && random_num(0,get_pcvar_num(p_choke_chance)) == 1)
				emit_sound(ent, CHAN_VOICE, fileNames[random_num(cough1, cough2)], 0.4, ATTN_NORM, 0, PITCH_NORM)		
	
			if(damage && random_num(0,get_pcvar_num(p_damage_chance)) == 1)
				{
				new grenade_owner = pev(grenid, pev_owner)
				
				if(!is_user_connected(grenade_owner))
					return PLUGIN_HANDLED
				
				new attacker_team = get_user_team(grenade_owner)
				new victim_team = get_user_team(ent)
				
				new friendlyfire = 0
				if(attacker_team == victim_team)
					friendlyfire = 1
						
				if(attacker_team != victim_team || (attacker_team == victim_team && get_cvar_num("mp_friendlyfire")))
					{
					new current_health = pev(ent, pev_health)
					new smoke_damage = get_pcvar_num(p_damage_amount)
						
					if(current_health > smoke_damage)
						{							
						emit_sound(ent, CHAN_VOICE, fileNames[random_num(cough1, cough2)], 0.6, ATTN_NORM, 0, PITCH_NORM)
						emit_sound(ent, CHAN_BODY, fileNames[grunt], 1.0, ATTN_NORM, 0, PITCH_NORM)
						
						set_pev(ent, pev_health, float(current_health - smoke_damage))
					
						new steam[32], teamname[32], name[32]
						get_user_authid(grenade_owner, steam, 31)
						dod_get_pl_teamname(grenade_owner, teamname, 31)
						get_user_name(grenade_owner, name, 31)
																
						log_message("^"%s<%d><%s><%s>^" triggered ^"weaponstats^" (weapon ^"smoke_grenade^") (shots ^"0^") (hits ^"1^") (kills ^"0^") (headshots ^"0^") (tks ^"0^") (damage ^"%d^") (deaths ^"0^") (score ^"0^")",name,get_user_userid(grenade_owner),steam,teamname,smoke_damage)
						}
					else
						{
						emit_sound(ent, CHAN_VOICE, fileNames[random_num(cough1, cough2)], 0.6, ATTN_NORM, 0, PITCH_NORM)
						emit_sound(ent, CHAN_BODY, fileNames[grunt], 1.0, ATTN_NORM, 0, PITCH_NORM)
							
						log_block_state = true
						user_silentkill(ent)
						log_block_state = false
						
						message_begin(MSG_ALL, gMsgDeathMsg,{0,0,0}, 0)
						write_byte(grenade_owner)
						write_byte(ent)
						write_byte(0)
						message_end()
		
						new steam[32],teamname[32],name[32]
						new steam2[32],teamname2[32],name2[32]
						get_user_authid(grenade_owner, steam, 31)
						get_user_authid(ent, steam2, 31)
						dod_get_pl_teamname(grenade_owner, teamname, 31)
						dod_get_pl_teamname(ent, teamname2, 31)
						get_user_name(grenade_owner, name, 31)
						get_user_name(ent, name2, 31)
						new userid = get_user_userid(grenade_owner)
						new userid2 = get_user_userid(ent)
						
						log_message("^"%s<%d><%s><%s>^" killed ^"%s<%d><%s><%s>^" with ^"smoke_grenade^"", name, get_user_userid(grenade_owner), steam, teamname, name2, get_user_userid(ent), steam2, teamname2)
					
						//killer
						log_message("^"%s<%d><%s><%s>^" triggered ^"weaponstats^" (weapon ^"smoke_grenade^") (shots ^"0^") (hits ^"1^") (kills ^"1^") (headshots ^"0^") (tks ^"%d^") (damage ^"%d^") (deaths ^"0^") (score ^"0^")",name,userid,steam,teamname,friendlyfire,smoke_damage)
						log_message("^"%s<%d><%s><%s>^" triggered ^"weaponstats2^" (weapon ^"smoke_grenade^") (head ^"0^") (chest ^"1^") (stomach ^"0^") (leftarm ^"0^") (rightarm ^"0^") (leftleg ^"0^") (rightleg ^"0^")",name,userid,steam,teamname)
				
						//victim
						log_message("^"%s<%d><%s><%s>^" triggered ^"weaponstats^" (weapon ^"smoke_grenade^") (shots ^"0^") (hits ^"0^") (kills ^"0^") (headshots ^"0^") (tks ^"0^") (damage ^"0^") (deaths ^"1^") (score ^"0^")",name2,userid2,steam2,teamname2)
					
						new kills = dod_get_user_kills(grenade_owner) + 1
						dod_set_user_kills(grenade_owner, kills,0)
						
						message_begin(MSG_BROADCAST, gMsgFrags, {0,0,0}, 0)
						write_byte(grenade_owner)
						write_short(kills)
						message_end()
						}					
					}
				}
			}
		}
		
	return PLUGIN_HANDLED
}
///////////////////////////////////////////////////////////////////////////////////////
//
// Check if the grenade has hit a wall or ground
//
public grenade_touch(grenid,object)
{
	if(!get_pcvar_num(p_smoke) || !pev_valid(grenid))
		return FMRES_IGNORED
	
	new classname[32]
	pev(grenid,pev_classname, classname, 31)
	
	if(equali(classname,"dod_smoke"))
		{		
		new obj_classname[32]
		pev(object,pev_classname, obj_classname, 31)
		
		// get the current vector
		new Float:NewVector[3]
		pev(grenid, pev_velocity, NewVector)
			
		// add a bit of static friction (slows it down)
		NewVector[0] *= 0.8 //0.65
		NewVector[1] *= 0.8
		NewVector[2] *= 0.8	
			
		set_pev(grenid, pev_velocity, NewVector)
		
		new Float:gametime = get_gametime()
			
		// add friction
		if(!equali(obj_classname,"player"))
			{
			new Float:currOrigin[3]
			pev(grenid,pev_origin,currOrigin)
	
			new Float:lastOrigin[3]
			lastOrigin[0] = Float:pev(grenid,pev_iuser1)
			lastOrigin[1] = Float:pev(grenid,pev_iuser2)
			lastOrigin[2] = Float:pev(grenid,pev_iuser3)
	
			if(get_distance_f(currOrigin,lastOrigin) < 2.0)
				return FMRES_IGNORED
			else
				{
				set_pev(grenid,pev_iuser1,currOrigin[0])
				set_pev(grenid,pev_iuser2,currOrigin[1])
				set_pev(grenid,pev_iuser3,currOrigin[2])
				}
				
			// play bounce sound
			switch(random_num(0,2))
				{
				case 0:	emit_sound(grenid, CHAN_ITEM, fileNames[hit1], 0.3, ATTN_NORM, 0, PITCH_NORM)
				case 1:	emit_sound(grenid, CHAN_ITEM, fileNames[hit2], 0.3, ATTN_NORM, 0, PITCH_NORM)
				case 2:	emit_sound(grenid, CHAN_ITEM, fileNames[hit3], 0.3, ATTN_NORM, 0, PITCH_NORM)
				}
			}
		else if(is_user_connected(object) && is_user_alive(object) && gametime > hitTime[object])
			{
			
			hitTime[object] = gametime + 1.2	
			
			new grenade_owner = pev(grenid, pev_owner)
			
			if(!is_user_connected(grenade_owner))
				return PLUGIN_HANDLED
			
			new attacker_team = get_user_team(grenade_owner)
			new victim_team = get_user_team(object)
			
			new friendlyfire = 0
			if(attacker_team == victim_team)
				friendlyfire = 1
				
			if(get_pcvar_num(p_hitdmg) && (!friendlyfire || (friendlyfire && get_cvar_num("mp_friendlyfire"))))
				{
				new current_health = pev(object, pev_health)
				new hit_damage = get_pcvar_num(p_hitdmg_amount)
				
				if(current_health > hit_damage)
					{
					set_pev(object, pev_health, float(current_health - hit_damage))
					
					new steam[32], teamname[32], name[32]
					get_user_authid(grenade_owner, steam, 31)
					dod_get_pl_teamname(grenade_owner, teamname, 31)
					get_user_name(grenade_owner, name, 31)
					new userid = get_user_userid(grenade_owner)
					
					new bp_chest = 0,bp_stomach = 0,bp_leftarm = 0,bp_rightarm = 0,bp_leftleg = 0,bp_rightleg = 0
					switch(random_num(1,6))
						{
						case 1: bp_chest = 1
						case 2: bp_stomach = 1
						case 3: bp_leftarm = 1
						case 4: bp_rightarm = 1
						case 5: bp_leftleg = 1
						case 6: bp_rightleg = 1
						}
									
					log_message("^"%s<%d><%s><%s>^" triggered ^"weaponstats^" (weapon ^"smoke_grenade^") (shots ^"0^") (hits ^"1^") (kills ^"0^") (headshots ^"0^") (tks ^"0^") (damage ^"%d^") (deaths ^"0^") (score ^"0^")",name,userid,steam,teamname,hit_damage)
					log_message("^"%s<%d><%s><%s>^" triggered ^"weaponstats2^" (weapon ^"smoke_grenade^") (head ^"0^") (chest ^"%d^") (stomach ^"%d^") (leftarm ^"%d^") (rightarm ^"%d^") (leftleg ^"%d^") (rightleg ^"%d^")",name,userid,steam,teamname,bp_chest,bp_stomach,bp_leftarm,bp_rightarm,bp_leftleg,bp_rightleg)
	
					}
				else
					{
					log_block_state = true
					user_silentkill(object)
					log_block_state = false
					
					message_begin(MSG_ALL, gMsgDeathMsg,{0,0,0}, 0)
					write_byte(grenade_owner)
					write_byte(object)
					write_byte(0)
					message_end()
	
					new steam[32],teamname[32],name[32]
					new steam2[32],teamname2[32],name2[32]
					get_user_authid(grenade_owner, steam, 31)
					get_user_authid(object, steam2, 31)
					dod_get_pl_teamname(grenade_owner, teamname, 31)
					dod_get_pl_teamname(object, teamname2, 31)
					get_user_name(grenade_owner, name, 31)
					get_user_name(object, name2, 31)
					new userid = get_user_userid(grenade_owner)
					new userid2 = get_user_userid(object)
						
					new bp_head = 0,bp_chest = 0,bp_stomach = 0,bp_leftarm = 0,bp_rightarm = 0,bp_leftleg = 0,bp_rightleg = 0
					switch(random_num(0,6))
						{
						case 0: bp_head = 1
						case 1: bp_chest = 1
						case 2: bp_stomach = 1
						case 3: bp_leftarm = 1
						case 4: bp_rightarm = 1
						case 5: bp_leftleg = 1
						case 6: bp_rightleg = 1
						}
					
					log_message("^"%s<%d><%s><%s>^" killed ^"%s<%d><%s><%s>^" with ^"smoke_grenade^"", name, userid, steam, teamname, name2, userid2, steam2, teamname2)
					
					//killer
					log_message("^"%s<%d><%s><%s>^" triggered ^"weaponstats^" (weapon ^"smoke_grenade^") (shots ^"0^") (hits ^"1^") (kills ^"1^") (headshots ^"%d^") (tks ^"%d^") (damage ^"%d^") (deaths ^"0^") (score ^"0^")",name,userid,steam,teamname,bp_head,friendlyfire,hit_damage)
					log_message("^"%s<%d><%s><%s>^" triggered ^"weaponstats2^" (weapon ^"smoke_grenade^") (head ^"%d^") (chest ^"%d^") (stomach ^"%d^") (leftarm ^"%d^") (rightarm ^"%d^") (leftleg ^"%d^") (rightleg ^"%d^")",name,userid,steam,teamname,bp_head ,bp_chest ,bp_stomach ,bp_leftarm ,bp_rightarm ,bp_leftleg ,bp_rightleg)
				
					//victim
					log_message("^"%s<%d><%s><%s>^" triggered ^"weaponstats^" (weapon ^"smoke_grenade^") (shots ^"0^") (hits ^"0^") (kills ^"0^") (headshots ^"0^") (tks ^"0^") (damage ^"0^") (deaths ^"1^") (score ^"0^")",name2,userid2,steam2,teamname2)
				
					new kills = dod_get_user_kills(grenade_owner) + 1
					dod_set_user_kills(grenade_owner,kills,0)
					
					message_begin(MSG_BROADCAST, gMsgFrags, {0,0,0}, 0)
					write_byte(grenade_owner)
					write_short(kills)
					message_end()
					}
						
				emit_sound(grenid, CHAN_BODY, fileNames[splat], 0.8, ATTN_NORM, 0, PITCH_NORM)
				emit_sound(grenid, CHAN_ITEM, fileNames[hit1], 0.6, ATTN_NORM, 0, PITCH_NORM)
		
				emit_sound(object, CHAN_VOICE, fileNames[grunt], 1.0, ATTN_NORM, 0, PITCH_NORM)
				}
			else
				{
				switch(random_num(0, 2))
					{
					case 0:	emit_sound(grenid, CHAN_ITEM, fileNames[hit1], 0.8, ATTN_NORM, 0, PITCH_NORM)
					case 1:	emit_sound(grenid, CHAN_ITEM, fileNames[hit2], 0.8, ATTN_NORM, 0, PITCH_NORM)
					case 2:	emit_sound(grenid, CHAN_ITEM, fileNames[hit3], 0.8, ATTN_NORM, 0, PITCH_NORM)
					}	
				}
			}
		}
	
	return FMRES_IGNORED
}

///////////////////////////////////////////////////////////////////////////////////////
//
// Trap the round message and handle
//
public round_message() 
{
	if(read_data(1) == 1)
		g_round_restart = false
	else
		{	
		g_round_restart = true
		    
		// Check to see if there are any smoke grenades out
		new grenid = engfunc(EngFunc_FindEntityByString, -1, "classname", "dod_smoke")
		
		while((grenid = engfunc(EngFunc_FindEntityByString, -1, "classname", "dod_smoke")) > 0)
			{
			// Remove sounds
			emit_sound(grenid, CHAN_WEAPON, fileNames[explode_smoke], 0.75, ATTN_NORM, SND_STOP, PITCH_NORM)
		    
			// trigger removal and re-use of the grenade as per the delay setting
			engfunc(EngFunc_RemoveEntity, grenid)
			smokeCount--
	    
			// Reset the emmited for this entity
			g_startGrenade[grenid] = false
	    
			// stop tasks if they havent been already
			if(task_exists(grenid))
				remove_task(grenid)
			}
		}
}

///////////////////////////////////////////////////////////////////////////////////////
//
// client spawn
//
public player_spawn(id)
{
	if(!get_pcvar_num(p_smoke) || !is_user_alive(id) || !is_user_connected(id) || is_user_bot(id))
		return PLUGIN_CONTINUE
	
	give_smoke(id)
	
	return PLUGIN_CONTINUE
}

///////////////////////////////////////////////////////////////////////////////////////
//
// Give a Smoke - give_smoke
//
give_smoke(id)
{
	new team = get_user_team(id)
	
	if(team == ALLIES)
		{
		switch(dod_get_user_class(id))
			{
			case DODC_GARAND: playerGrensCount[id] = get_cvar_num("dod_smoke_garand")
			case DODC_CARBINE: playerGrensCount[id] = get_cvar_num("dod_smoke_carbine")
			case DODC_THOMPSON: playerGrensCount[id] = get_cvar_num("dod_smoke_thompson") 
			case DODC_GREASE: playerGrensCount[id] = get_cvar_num("dod_smoke_grease") 
			case DODC_SNIPER: playerGrensCount[id] = get_cvar_num("dod_smoke_sniper") 
			case DODC_BAR: playerGrensCount[id] = get_cvar_num("dod_smoke_bar") 
			case DODC_30CAL: playerGrensCount[id] = get_cvar_num("dod_smoke_30cal") 
			case DODC_BAZOOKA: playerGrensCount[id] = get_cvar_num("dod_smoke_bazooka")
			case DODC_ENFIELD: playerGrensCount[id] = get_cvar_num("dod_smoke_enfield") 
			case DODC_STEN: playerGrensCount[id] = get_cvar_num("dod_smoke_sten") 
			case DODC_MARKSMAN: playerGrensCount[id] = get_cvar_num("dod_smoke_marksman") 
			case DODC_BREN: playerGrensCount[id] = get_cvar_num("dod_smoke_bren") 
			case DODC_PIAT: playerGrensCount[id] = get_cvar_num("dod_smoke_piat")
			}
		}
	else if(team == AXIS)
		{	
		switch(dod_get_user_class(id))
			{
			case DODC_KAR: playerGrensCount[id] = get_cvar_num("dod_smoke_kar") 
			case DODC_K43: playerGrensCount[id] = get_cvar_num("dod_smoke_k43") 
			case DODC_MP40: playerGrensCount[id] = get_cvar_num("dod_smoke_mp40") 
			case DODC_MP44: playerGrensCount[id] = get_cvar_num("dod_smoke_mp44") 
			case DODC_SCHARFSCHUTZE: playerGrensCount[id] = get_cvar_num("dod_smoke_scharfschutze") 
			case DODC_FG42: playerGrensCount[id] = get_cvar_num("dod_smoke_fg42") 
			case DODC_SCOPED_FG42: playerGrensCount[id] = get_cvar_num("dod_smoke_scoped_fg42") 
			case DODC_MG34: playerGrensCount[id] = get_cvar_num("dod_smoke_mg34") 
			case DODC_MG42: playerGrensCount[id] = get_cvar_num("dod_smoke_mg42") 
			case DODC_PANZERJAGER: playerGrensCount[id] = get_cvar_num("dod_smoke_panzerjager")
			}
		}
		
	if(get_pcvar_num(p_msg_spawn))
		client_print(id, print_chat, "You have %d Smoke %s...", playerGrensCount[id], (playerGrensCount[id] > 1) ? "Grenades" : "Grenade")

}

public enforce(const file[])
{
	if(file_exists(file) && equali(fileNames[sprites],file))
		force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, file)
}

public inconsistent_file(id, const filename[], reason[64])
{
	if(equali(fileNames[sprites],filename))
		{
		new nick[32], steamid[32], userid
		
		get_user_authid(id, steamid, 31)
		get_user_name(id, nick, 31)
		userid = get_user_userid(id)
		
		new output[128]
		format(output, 127, "^"%s<%d><%s>^" inconsistent file ^"%s^"", nick, userid, steamid, filename)
		
		// No matter what Im logging the infraction
		log_amx("%s", output)
		
		switch(get_pcvar_num(p_smoke_warncrc))
			{
			case 1: {
				new players[32], num
				get_players(players,num,"c")
				
				for(new i = 0; i < num; i++)
					{
					new admin_id = players[i]
						
					if(get_user_flags(admin_id) & ADMIN_KICK)
						client_print(admin_id, print_chat, "%s", output)
					}
				}
			case 2: {
				client_cmd(0,"spk ^"fvox/beep^"")
				
				set_hudmessage(random_num(1, 255), random_num(1, 255), random_num(1, 255), 0.03, 0.4, 0, 6.0, 5.0, 0.1, 0.2, 4)
				show_hudmessage(0, "WARNING!!^n%s^nhas an inconsistent smoke grenade sprite!^nDenying them access into the server...", nick)
				
				client_print(0, print_chat,"WARNING!! %s has an inconsistent smoke grenade sprite! Denying them access into the server...", nick)
				}
			}
		
		format(reason, 63, "- delete %s and retry!", filename)
		}
	
	return PLUGIN_CONTINUE
}

///////////////////////////////////////////////////////////////////////////////////////
// Block suicide log
//
public block_log(type, msg[])
{
	return(log_block_state?FMRES_SUPERCEDE:FMRES_IGNORED)
}

#if DEBUG_MODE == 1

public debug_givesmoke(id,level,cid)
{
	if(cmd_access(id, level, cid, 1))
		playerGrensCount[id] += 5
		
	return PLUGIN_HANDLED
}

#endif
